package com.foxchen.ddns.core;

import cn.hutool.extra.mail.MailUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.foxchen.ddns.config.CpuCheckConfig;
import com.foxchen.ddns.config.DDNSConfig;
import com.foxchen.ddns.service.impl.IpGetService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Component
public class ServerStatusListener {
    @Resource
    private CpuCheckConfig cpuCheckConfig;
    @Resource
    private DDNSConfig ddnsConfig;
    @Resource
    private IpGetService ipGetService;
    private static final Map<String,Double> CPU_USAGE = new HashMap<>();
    private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @PostConstruct
    @SuppressWarnings("InfiniteLoopStatement")
    public void listenerServer() {
        String jvmName = System.getProperty("java.vm.name");
        String jvmVendor = System.getProperty("java.vm.vendor");
        String jvmVersion = System.getProperty("java.vm.version");

        log.info("jvmName={},jvmVendor={},jvmVersion={}", jvmName, jvmVendor, jvmVersion);
        if(!jvmName.toLowerCase().contains("hotspot")){
            log.warn("this vm can not listener server.");
            return;
        }

        Runnable runnable = () -> {
            while (true) {
                try {
                    TimeUnit.SECONDS.sleep(cpuCheckConfig.getSingleRecord());
                    OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
                    String osJson = JSON.toJSONString(operatingSystemMXBean);
                    JSONObject jsonObject = JSON.parseObject(osJson);
                    double systemCpuLoad = jsonObject.getDouble("systemCpuLoad") * 100;
                    CPU_USAGE.put(SIMPLE_DATE_FORMAT.format(new Date()),systemCpuLoad);
                    checkCpuLoadAndSendEmail();
                }
                catch (Exception e){
                    log.error("listenerServer error",e);
                }
            }
        };

        ExecutorService executorService = Executors.newFixedThreadPool(1);
        executorService.execute(runnable);
    }

    private void checkCpuLoadAndSendEmail(){
        // 如果记录数量已经到达了 持续时间/单词记录的时间 记录平均使用率 超过阈值即视作异常
        if(CPU_USAGE.size() == cpuCheckConfig.getDurationTime() / cpuCheckConfig.getSingleRecord()){
            double cpuAvgUse = CPU_USAGE.values().stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
            log.info("DurationTime is:{},singleRecord is:{},avg is:{},detail:{}",cpuCheckConfig.getDurationTime(),cpuCheckConfig.getSingleRecord(),cpuAvgUse,CPU_USAGE);
            List<String> timeList = CPU_USAGE.keySet().stream().sorted(String::compareTo).collect(Collectors.toList());
            String beginTime = timeList.get(0);
            String endTime = timeList.get(CPU_USAGE.size() - 1);
            if(cpuAvgUse >= cpuCheckConfig.getThreshold()){
                String localPublicIp = ipGetService.getLocalPublicIp(ddnsConfig.getDefaultIpType());
                String title = String.format(cpuCheckConfig.getEmailTile(), localPublicIp);
                String msg = String.format(cpuCheckConfig.getEmailMsg(), localPublicIp,beginTime,endTime,cpuAvgUse,cpuCheckConfig.getThreshold());
                log.warn("cpu usage looks like error,now will be send email,server ip:{},title:{},msg:{},config:{}",localPublicIp,title,msg,cpuCheckConfig);
                MailUtil.send(cpuCheckConfig.getEmailAddress(), title, msg, false);
            }

            CPU_USAGE.clear();
        }
    }
}
